home *** CD-ROM | disk | FTP | other *** search
Wrap
Text File | 1994-12-08 | 43.2 KB | 1,309 lines | [ TEXT/R*ch]
C.S.M.P. Digest Tue, 20 Oct 92 Volume 1 : Issue 191 Today's Topics: Calling a resource as code? Creating a floating palette in MacApp Access to Map cdev data Slaughtering Lambs in the Name of Jim Reekes Setting the volume I need a *fast* rand () procedure MacTCP: can't send very many single bytes in a row AppleEvent passing address THINK Pascal v4.01 and 32-bit The Comp.Sys.Mac.Programmer Digest is moderated by Michael A. Kelly. The digest is a collection of article threads from the internet newsgroup comp.sys.mac.programmer. It is designed for people who read c.s.m.p. semi- regularly and want an archive of the discussions. If you don't know what a newsgroup is, you probably don't have access to it. Ask your systems administrator(s) for details. (This means you can't post questions to the digest.) Each issue of the digest contains one or more sets of articles (called threads), with each set corresponding to a 'discussion' of a particular subject. The articles are not edited; all articles included in this digest are in their original posted form (as received by our news server at cs.uoregon.edu). Article threads are not added to the digest until the last article added to the thread is at least one month old (this is to ensure that the thread is dead before adding it to the digest). Article threads that consist of only one message are generally not included in the digest. The entire digest is available for anonymous ftp from ftp.cs.uoregon.edu [128.223.8.8] in the directory /pub/mac/csmp-digest. Be sure to read the file /pub/mac/csmp-digest/README before downloading any files. The most recent issues are available from sumex-aim.stanford.edu [36.44.0.6] in the directory /info-mac/digest/csmp. If you don't have ftp capability, the sumex archive has a mail server; send a message with the text '$MACarch help' (no quotes) to LISTSERV@ricevm1.rice.edu for more information. The digest is also available via email. Just send a note saying that you want to be on the digest mailing list to mkelly@cs.uoregon.edu, and you will automatically receive each new issue as it is created. Sorry, back issues are not available through the mailing list. Send administrative mail to mkelly@cs.uoregon.edu. ------------------------------------------------------- From: clas005@csc.canterbury.ac.nz Subject: Calling a resource as code? Date: 4 Aug 92 14:27:15 +1200 Organization: University of Canterbury, Christchurch, New Zealand In Dave Mark's C Mac Programming Primer, an example is given of how to write an INIT/CDEV where he loads a resource (of type PROC, but this is not important) and calls it as executable code by using CallPascal(), handing off a pointer to the resource. My question is, how would I do this from within Pascal, specifically from within THINK Pascal? How can I force a resource to be regarded as code, and executed as a callable procedure? - ----- matt = CLAS005@csc.canterbury.ac.nz +++++++++++++++++++++++++++ From: Roger.W.Brown@dartmouth.edu (Roger W. Brown) Date: 4 Aug 92 14:54:09 GMT Organization: Dartmouth College, Hanover, NH In article <1992Aug4.142715.148@csc.canterbury.ac.nz> clas005@csc.canterbury.ac.nz writes: > My question is, how would I do this from within Pascal, > specifically from within THINK Pascal? How can I force a resource > to be regarded as code, and executed as a callable procedure? This is how we do it in MPW. I don't know if it will be the same in Think Pascal. Define an stub interface to the procedure with the proper parameters if there are any. This will be used to jump into the CODE using the inline statement. ex. FUNCTION MyExternalFunction(var s1,s2,s3: Str255; addr: ProcPtr):Boolean; inline $205F, $4E90; Get the resource, using its stripped address as the "addr" parameter: ex. {Get the function CODE module} {h is a Handle, kCodeID is a constant defining the resource ID, NoCodeError is an error number constant.} h := GetResource('CODE', kCodeID); if (h = nil) then Failure(NoCodeError,0); DetachResource(h); {Call the function module and return the result} HLock(h); functionResult := MyExternalFunction(str1,str2,str3,StripAddress(h^)); {Clean up} DisposHandle(h); - ----------------------------------------------------------------- Roger Brown Roger.W.Brown@dartmouth.edu Software Development Kiewit Computation Center Dartmouth College, Hanover, NH --------------------------- From: poon@parc.xerox.com (Alex Poon) Subject: Creating a floating palette in MacApp Organization: Xerox PARC Date: 22 Jul 92 21:32:54 GMT I want to create a floating palette in MacApp, much like Hypercard's tools window. I'd also like it to be resizable and scrollable. I've created a palette view in MacApp as a subview of TGridView, but the window that it's installed in becomes hidden when another window is activated on top of it. I want the palette window to always be showing, and I don't want any sense of it being activated or deactivated. Any suggestions? poon@parc.xerox.com +++++++++++++++++++++++++++ From: eyes@cs.ubc.ca (Eye Care Centre) Organization: Computer Science, University of B.C., Vancouver, B.C., Canada Date: Thu, 23 Jul 92 03:13:06 GMT In article <poon.711840774@roo> poon@parc.xerox.com (Alex Poon) writes: >I want to create a floating palette in MacApp, much like Hypercard's tools >window. I'd also like it to be resizable and scrollable. I've created >a palette view in MacApp as a subview of TGridView, but the window that >it's installed in becomes hidden when another window is activated >on top of it. I want the palette window to always be showing, and I don't >want any sense of it being activated or deactivated. MacApp 2.0.1 has floating window support provided in a folder containing experimental enhancements (I forget the exact name of the folder). Just move the files in this folder to your MacApp libraries sources folder and examine the included examples to see how to use the new classes. MacApp 3.0 has a built-in TFloatingWindow class. I'm not sure if it supports resizing, though, not having used it yet. Bill Kiss, Programmer Dept. of Ophthalmology, UBC +++++++++++++++++++++++++++ From: mlanett@Apple.COM (Mark Lanett) Date: 23 Jul 92 04:37:50 GMT Organization: Apple Computer Inc., Cupertino, CA poon@parc.xerox.com (Alex Poon) writes: >I want to create a floating palette in MacApp, much like Hypercard's tools >window. I'd also like it to be resizable and scrollable. I've created >a palette view in MacApp as a subview of TGridView, but the window that >it's installed in becomes hidden when another window is activated >on top of it. I want the palette window to always be showing, and I don't >want any sense of it being activated or deactivated. MacApp 3: trivial. Just create a window and hit the appropriate check boxes in ViewEdit. These will be: window type (WindoidWDEF), Floats, Doesn't Generate Actiavtes, Hides on Suspend. Create it like you would any other window and Ta-da! it'll float around. Like I said, trivial. Oh yes, you have to call InitUFloatWindow() in main(). MacApp 2: harder. 90% of it is done for you, it just that the last 10% is non-obvious. First off, there was an unsupported floating window package on ETO (there was a year ago when I used it, I can't get to an ETO now to check) that you'll need to incorporate. That's the 90% part. You need to specify the floating window resource template via Rez, not ViewEdit, because ViewEdit can't put out the refCon for the floating window. I had a Rez template with just the floater and put all my views in a separate view (created with ViewEdit). Creating a window becomes a matter of floater=NewTemplateWindow(...); DoCreateViews(floater,...); It's easier in 3.0, obviously. Also tabbing and other things are handled much better. Also there's a snippet doing floaters on the developer CD (also on ftp, I guess, but it's down right now), which is, alas, for MacApp 3.0b2. - -- /* Well, you wanted a command line interface, you got one, and now you can't figure out how to use it without the manual. What were you expecting? That's how command line interfaces work. - John Nagle */ +++++++++++++++++++++++++++ From: mcmath@csb1.nlm.nih.gov (Chuck McMath) Date: 23 Jul 92 14:19:19 GMT Organization: MSD In article <poon.711840774@roo>, poon@parc.xerox.com (Alex Poon) wrote: > > I want to create a floating palette in MacApp, much like Hypercard's tools > window. I'd also like it to be resizable and scrollable. I've created > a palette view in MacApp as a subview of TGridView, but the window that > it's installed in becomes hidden when another window is activated > on top of it. I want the palette window to always be showing, and I don't > want any sense of it being activated or deactivated. > > Any suggestions? > > poon@parc.xerox.com Well, if you're using MacApp 3.0 you can easily create a floating window with your stuff in it. There are additions to 2.0 to add floating palette capabilities. The additions work; I've used them successfully in a program I wrote. You need to set up the appropriate flags using ViewEdit (right?) and the palette window needs to be a TFloatWindow (this is 3.0 I'm describing here). It's not that difficult. chuck |- chuck mcmath - mcmath@csb1.nlm.nih.gov - MSD, Inc. ------------| |- National Library of Medicine - National Institutes of Health --| |- Bethesda, MD 20894 ------------ C++ causes cancer -------------| |- "Hey batter, hey batter, hey batter, swing" - Anon. -----------| +++++++++++++++++++++++++++ From: Kent Sandvik (Hacker) <ksand@apple.com> Date: Tue, 4 Aug 1992 17:46:25 GMT Organization: Apple In article <70364@apple.Apple.COM> Mark Lanett, mlanett@Apple.COM writes: >It's easier in 3.0, obviously. Also tabbing and other things are handled much >better. Also there's a snippet doing floaters on the developer CD (also on >ftp, I guess, but it's down right now), which is, alas, for MacApp 3.0b2. I'm going to fix this for 3.0.1 this Thursday. Don't worry! The other sample concerning behaviors I wrote also has a floating window. Kent Sandvik/DTS --------------------------- From: rdd@cactus.org (Robert Dorsett) Subject: Access to Map cdev data Organization: Capital Area Central Texas UNIX Society, Austin, Tx Date: Mon, 27 Jul 1992 05:34:00 GMT I haven't been able to find a good answer to this in IM: is there a way to access the lat/long data *and* the relative UTC time as entered in the Map cdev? I have a friend who's writing a satellite-tracker; it makes some sense for him to initialize his information from the map cdev. Please reply via email; I'll summarize. - --- Robert Dorsett rdd@cactus.org ...cs.utexas.edu!cactus.org!rdd +++++++++++++++++++++++++++ From: sdorner@qualcom.qualcomm.com (Steve Dorner) Organization: Qualcomm, Inc., San Diego, CA Date: Wed, 5 Aug 1992 15:01:25 GMT You wrote in comp.sys.mac.programmer: >I haven't been able to find a good answer to this in IM: is there a way >to access the lat/long data *and* the relative UTC time as entered in the >Map cdev? I have a friend who's writing a satellite-tracker; it makes >some sense for him to initialize his information from the map cdev. > >Please reply via email; I'll summarize. I know this is an old article, but I didn't see any summary. This is documented in (of all places) the Script Manager chapter of IM-5. The routine name is "ReadLocation". You cannot tell if the mac's time is DST or not; the "dlsDelta" flag mentioned is not implemented by anything; there are not even any units specified for it. - -- Steve Dorner, Qualcomm, Inc. Yes, I'm still working on Eudora and it's still free. --------------------------- From: d88-jwa@cyklop.nada.kth.se (Jon W{tte) Subject: Slaughtering Lambs in the Name of Jim Reekes Date: 4 Aug 92 13:21:56 GMT Organization: Royal Institute of Technology, Stockholm, Sweden This is the dying sound channel from hell problem. I am playing some sounds, asynchronously, and sometimes (repeatable but not predictable) the sound channel just dies and doesn't play anymore. Re-initting the channel makes sound come back. Any help appreciated, here's the code: (And you may use it with credits to me in your about box and a free copy of your app to me :-) // GameSounds.c #include "GameSounds.h" #include "Fail.h" Handle sounds [ NUM_SOUNDS ] ; Boolean ldRes = 0 ; SndChannelPtr sndChannel = NULL ; void LoadSounds ( void ) { int i ; if ( sndChannel ) { return ; } if ( ! ldRes ) { for ( i = 0 ; i < NUM_SOUNDS ; i ++ ) { sounds [ i ] = GetResource ( 'snd ' , i + 128 ) ; if ( ! sounds [ i ] ) { Fail ( -192 ) ; } { short * s = ( short * ) * sounds [ i ] ; if ( ( s [ 0 ] != 1 ) || ( s [ 1 ] != 1 ) ) { Fail ( -50 ) ; } } DetachResource ( sounds [ i ] ) ; MoveHHi ( sounds [ i ] ) ; HLock ( sounds [ i ] ) ; } ldRes = 1 ; } sndChannel = NULL ; i = SndNewChannel ( & sndChannel , sampledSynth , initMono + initNoInterp , NULL ) ; if ( i ) { Fail ( i ) ; } } void GameSound ( short ix ) { SndCommand cmd ; if ( ! sndChannel ) { LoadSounds ( ) ; } cmd . cmd = flushCmd ; cmd . param1 = 0 ; cmd . param2 = 0 ; // SndDoImmediate ( sndChannel , & cmd ) ; cmd . cmd = quietCmd ; cmd . param1 = 0 ; cmd . param2 = 0 ; SndDoImmediate ( sndChannel , & cmd ) ; cmd . cmd = bufferCmd ; cmd . param1 = 0 ; cmd . param2 = ( long ) ( ( char * ) * sounds [ ix ] ) + 20 ; SndDoCommand ( sndChannel , & cmd , TRUE ) ; cmd . cmd = quietCmd ; cmd . param1 = 0 ; cmd . param2 = 0 ; // SndDoCommand ( sndChannel , & cmd , TRUE ) ; } void DoneSounds ( void ) { SndCommand cmd ; if ( ! sndChannel ) { return ; } cmd . cmd = flushCmd ; cmd . param1 = 0 ; cmd . param2 = 0 ; SndDoImmediate ( sndChannel , & cmd ) ; cmd . cmd = quietCmd ; cmd . param1 = 0 ; cmd . param2 = 0 ; SndDoImmediate ( sndChannel , & cmd ) ; SndDisposeChannel ( sndChannel , TRUE ) ; sndChannel = NULL ; } void ReInitSounds ( void ) { SndCommand cmd ; if ( ! sndChannel ) { LoadSounds ( ) ; } cmd . cmd = flushCmd ; cmd . param1 = 0 ; cmd . param2 = 0 ; SndDoImmediate ( sndChannel , & cmd ) ; cmd . cmd = quietCmd ; cmd . param1 = 0 ; cmd . param2 = 0 ; SndDoImmediate ( sndChannel , & cmd ) ; cmd . cmd = reInitCmd ; cmd . param1 = 0 ; cmd . param2 = initMono + initNoInterp ; SndDoImmediate ( sndChannel , & cmd ) ; } - -- Jon W{tte, Svartmangatan 18, S-111 29 Stockholm, Sweden h+@nada.kth.se +46-10-141652 My landlord have forbidden my cat to run around on the roof. +++++++++++++++++++++++++++ From: rbarris@orion.oac.uci.edu (Robert C. Barris) Organization: University of California, Irvine Date: 6 Aug 92 05:47:42 GMT In article <D88-JWA.92Aug4142157@cyklop.nada.kth.se> d88-jwa@cyklop.nada.kth.se (Jon W{tte) writes: > >This is the dying sound channel from hell problem. > >I am playing some sounds, asynchronously, and sometimes >(repeatable but not predictable) the sound channel just >dies and doesn't play anymore. Re-initting the channel >makes sound come back. I have seen this and had to deal with it. In a nutshell, the Sound Manager is not perfect. If it misses an interrupt from the ASC for any reason (LocalTalk is popular cause) then it just forgets about that output channel (and it never gets fed again). I encountered this problem when using SndPlayDoubleBuffer, and ultimately implemented a watchdog routine which kept track of the number of ticks elapsed since the last block of data transferred to the sound chip. If that number ever went above a certain threshold, it figured 'oops, the channel stalled' and re-initted it as you mentioned. Obviously it would be nice if the SndMgr did this for us. Rob Barris Quicksilver Software Inc. rbarris@orion.oac.uci.edu --------------------------- From: essam@gagme.chi.il.us (Essam Khairullah) Subject: Setting the volume Organization: Gagme Public Access UNIX, Chicago, Illinois. Date: Mon, 3 Aug 1992 20:08:50 GMT I've been trying to write an XCMD to set the speaker volume (in THINK C 5.0) and I have this weird problem.... Basically I originally tried reading the parameter RAM, changing the appropriate bits for the sound volume, and then writing it back. I then discovered the low memory global SdVolume. Both methods seemed to work, except for the following problem: Basically the sound volume would not be effected until I activate AfterDark (by moving the mouse into the appropriate corner) or I open the Sound control panel and play a sound. If I just SysBeep without doing one of the above things firstthe old volume would be used. But if I do one of the above, the sound volume that I was trying to set would be used. My XCMD is actually an XFCN which also returns the current sound volume. If I call it again after setting the volume, the volume it returns is also the right volume. What am I doing wrong? Do I need to do something like InitSoundManager (which as far as IM 1-6 are concerned, doesn't exist). Do I have to open a new sound channel or something? Please let me know if you have any advice! Thanks in advance... - -- Essam Badi' Abu Khalil Khairullah essam@gagme.chi.il.us I don't got no fancy signature! I'm a .signature virus. You can't resist copying me into your .signature! +++++++++++++++++++++++++++ From: jeremyr@dcs.qmw.ac.uk (Jeremy Roussak) Date: 6 Aug 92 18:23:13 GMT Organization: Computer Science Dept, QMW, University of London In <1992Aug3.200850.14026@gagme.chi.il.us> essam@gagme.chi.il.us (Essam Khairullah) writes: >I've been trying to write an XCMD to set the speaker volume... >Basically I originally tried reading the parameter RAM, changing the appropriate >bits for the sound volume, and then writing it back. I then discovered the low >memory global SdVolume. Both methods seemed to work, except for the following >problem: [changes not activated until After Dark run] >What am I doing wrong? There are two relevant low-memory globals. SpVolCtl is a byte which reflects the parameter RAM volume setting in its low 3 bits. SdVolume is a byte which contains the current speaker volume. GetSoundVolume() returns the current value of SdVolume. SetSoundVolume(short) sets SdVolume to the specified value, with immediate effect, but the change will not persist after restart. Changing the low 3 bits of SpVolCtl and then calling WriteParam makes a change which will come into effect after restart, or perhaps after running the Sound CP. So, to change the volume, call GetSoundVolume and SetSoundVolume: don't forget to be responsible and call SetSoundVolume again to restore the level to make a permanent change, do the above and also set SpVolCtl and call WriteParam. I think the above is correct :-) Jeremy --------------------------- From: psc9q@holmes.acc.Virginia.EDU (The Beloved) Subject: I need a *fast* rand () procedure Organization: University of Virginia Date: Wed, 5 Aug 1992 06:25:00 GMT Hello, I'm creating bitmaps filled with a certain percentage of dots. Basically, I just test to see if "rand () % 100" is less than say, 25%, and draw a point. Does anyone know of a faster way to do this? I've rewritten rand.c in assembly but only received a 50% speed improvement. I need something drastically faster. Below is my assembly code. Could I optimize this somehow? unsigned long newRand = 1; int fastrand () { unsigned int tempRand; asm { move.l newRand, d0 mulu.l #1103515245, d0 add.w #12345, d0 move.l d0, newRand lsr.l #8, d0 lsr.l #8, d0 and.w #32767, d0 move.w d0, tempRand } return (tempRand); } Thanks, Paul - -- beloved@virginia.edu "Top one, nice one, get sorted." psc9q@holmes.acc.virginia.edu -- Altern8 +++++++++++++++++++++++++++ From: buckeye@spf.trw.com (John Wallace) Organization: TRW Data Systems Center, Redondo Beach, CA Date: Wed, 5 Aug 92 20:42:59 GMT In article <1992Aug5.062500.17133@murdoch.acc.Virginia.EDU> psc9q@holmes.acc.Virginia.EDU (The Beloved) writes: >Hello, > >I'm creating bitmaps filled with a certain percentage of dots. Basically, I >just test to see if "rand () % 100" is less than say, 25%, and draw a point. >Does anyone know of a faster way to do this? I've rewritten rand.c in assembly >but only received a 50% speed improvement. I need something drastically >faster. Below is my assembly code. Could I optimize this somehow? > >unsigned long newRand = 1; > >int fastrand () >{ > unsigned int tempRand; > > asm > { > move.l newRand, d0 > mulu.l #1103515245, d0 > add.w #12345, d0 > move.l d0, newRand > lsr.l #8, d0 > lsr.l #8, d0 > and.w #32767, d0 > move.w d0, tempRand > } > > return (tempRand); >} > >Thanks, > >Paul >-- >beloved@virginia.edu "Top one, nice one, get sorted." >psc9q@holmes.acc.virginia.edu -- Altern8 There are a couple of things you may want to do to speed things up. Rather than shifting by 16, just call the 'swap' command to move the high word into the low word. Also, why do you add 32767? This will just convert all of your positives into negatives and your negatives into positives, so it seems to be of no possible value. Also rather than doing it rand()%100, you may want to do it rand()%128, which you would implement as rand()&127, since the % operation is quite slow. Then rather than comparing it to 25, you can compare it to 25*(128/100), where you compute that value only once outside of your pixel plotting code. You may also want to the the %128 operation in the code itself, and since C returns values in d0 (I think; I do most of my high level coding in Pascal), you could recode the entire thing as: unsigned long newRand = 1; int RandMod128 () { asm { move.l newRand, d0 mulu.l #1103515245, d0 add.w #12345, d0 move.l d0, newRand swap d0 ; move high word of random value into low word and.w #127,d0 ; get value in range from 0..127 unlink a6 ; undo the C routine's link a6 rts ; return to caller } } Cheers! John - ------------- John Wallace buckeye@spf.trw.com +++++++++++++++++++++++++++ From: k044477@hobbes.kzoo.edu (Jamie R. McCarthy) Organization: Kalamazoo College Date: Wed, 5 Aug 1992 21:43:15 GMT I don't want to pick on you, John, but I just have to say this... :-) buckeye@spf.trw.com (John Wallace) writes: >psc9q@holmes.acc.Virginia.EDU (The Beloved) writes: >> >>I'm creating bitmaps filled with a certain percentage of dots. Basically, I >>just test to see if "rand () % 100" is less than say, 25%, and draw a point. > >There are a couple of things you may want to do to speed things up. >Rather than shifting by 16, just call the 'swap' command to move the >high word into the low word. True--twice as fast... >Also, why do you add 32767? He 'and'ed, which masks off the lower 16 bits (which doesn't affect the result, in this case...) >Also rather than doing it rand()%100, you may want to do it >rand()%128, which you would implement as rand()&127, since the % >operation is quite slow. Then rather than comparing it to 25, you can >compare it to 25*(128/100) In C, 25*(128/100) equals 25. I suspect you want (25*128)/100. >...since C returns values in d0 (I think; I do most of my high level >coding in Pascal), you could recode...: > >int RandMod128 () >{ > asm > { > move.l newRand, d0 > mulu.l #1103515245, d0 > add.w #12345, d0 > move.l d0, newRand > swap d0 ; move high word of random value into low word > and.w #127,d0 ; get value in range from 0..127 > unlink a6 ; undo the C routine's link a6 > rts ; return to caller > } >} This will work (except that "unlink" is spelled "unlk"), but, as the manual says, "Do not use the RTS instruction unless you're absolutely sure you know what you're doing. If you want to return a value, always use a return statement." In this case, I believe the compiler won't be smart enough to realize you're returning inside the asm block, and will put its own unlk and rts right after yours. More important (to me) is the unlk that matches up with the hidden one at the top of the function. If you rewrite RandMod128 to use a local variable, you'd better be alert enough to catch this. This kind of coding makes me nervous. If speed is so important that you can't take the time to push and pop the return value, you should be inlining this function anyway, and putting both newRand and the constant #12345 into registers if at all possible. Finally, I hope this code won't be run on a 68000; it doesn't have a longword multiply instruction... - -- Jamie McCarthy Internet: k044477@kzoo.edu AppleLink: j.mccarthy "When the Constitution was adopted...no human wisdom could foretell the sweeping changes...which were to take place.... The conditions are now wholly different, and wholly different action is called for." - T. Roosevelt, 1901 +++++++++++++++++++++++++++ From: kaufman@Xenon.Stanford.EDU (Marc T. Kaufman) Organization: CS Department, Stanford University, California, USA Date: 6 Aug 92 00:51:09 GMT psc9q@holmes.acc.Virginia.EDU (The Beloved) writes: >I'm creating bitmaps filled with a certain percentage of dots. Basically, I >just test to see if "rand () % 100" is less than say, 25%, and draw a point. For the random number generator, if you have a 69020 try this: move.l RandomSeed,D1 mulu.l #16807,D0:D1 ; long multiply divu.l #$7fffffff,D0:D1 ; modulo 2^31 -1 move.l D0,RandomSeed - -- Marc Kaufman (kaufman@CS.Stanford.EDU) +++++++++++++++++++++++++++ From: creiman@Apple.COM (Charlie Reiman) Date: 5 Aug 92 23:54:00 GMT Organization: Apple Computer Inc., Cupertino, CA psc9q@holmes.acc.Virginia.EDU (The Beloved) writes: >Hello, >I'm creating bitmaps filled with a certain percentage of dots. Basically, I >just test to see if "rand () % 100" is less than say, 25%, and draw a point. >Does anyone know of a faster way to do this? I've rewritten rand.c in assembly >but only received a 50% speed improvement. I need something drastically >faster. Below is my assembly code. Could I optimize this somehow? < Code deleted > Is it just me, or does every UseNet programming group seem to deal with this issue at least once a year? Now that my obligitory nit-picking is done, let's get down to business. First off: using n%100 is bad. It involves taking an integer division, which is unnecessary. Use (n & 0xff) < 0x40 or some such. Remember: Logical AND is the same as integer modulus. Also, don't assume the compiler is smart enough to translate ( N % 256 ) => ( N & 255 ). Last time I checked, MPW C wasn't managing the simlar translation for division so I wouldn't count on it working for modulus. If you are looking for speed, there is one easy way to get what you need. In your case there happens to be a second, sneaky way that I'll also mention last. 1) Buffers. Create a small buffer of, oh, say 16 words. Fill 'em with random numbers. Then create a counter, and init it to zero and an index into the table, also inited to zero. When you need a random number, call a routine that works like this: returnValue = table[index] index = (index + 1) mod 16 # yes, you should use & 0xf, but this is counter += 1 # pseudo-code. if ( counter == 7 ) table[index]=Random() counter = 0 return returnValue This is cheap and easy. It will also reduce the randomness of your numbers quite a bit. Just be sure you don't fall into mindless loops (ie. change the counter ceiling to 8. Only two values in the buffer will change in this case) Needless to say, you shouldn't use this algorithim for any scientific computations. In case you haven't noticed, I didn't test this code before posting it. Caveat Emptor. 2) Tiling. Create a small tile of the appropriate darkness, then tile it over the entire bitmap using copybits. Good luck. - -- Charlie Reiman - Speaking as an individual, not for Apple Computer. creiman@apple.com "NEW! Posting Lite! 98% fact free!" +++++++++++++++++++++++++++ From: bruner@sp15.csrd.uiuc.edu (John Bruner) Organization: CSRD, University of Illinois Date: 6 Aug 92 09:03:31 Using a pseudo-random number generator to create a large bitmap is, by nature, going to be slow. If the intent of the code is to do some sort of image dithering, I suggest you consult the recent issue of *develop* (the "Winter 1992" issue, I believe), where the topic was discussed. If you really do need to generate pseudo-random numbers and test them against a threshold, I suggest that you treat the values as 32-bit unsigned fixed point numbers and do the threshold with a comparison rather than shifting and masking. You could use the fixed point routines the the Toolbox provides, but they use a different representation, so you'd have to account for that. Alternately, you can do something like the following: 1) Generate a 32-bit fraction representing the desired percentage. This requires a divide (which makes it expensive), but presumably you will only do this once, whereas you will generate many pseudo-random numbers. You produce the fraction by dividing 100 into a 64-bit number whose binary point is located right in the middle, i.e., you want to divide (percentage<<32) by 100. Assuming "percentage" is less than 100 this will produce a 32-bit quotient with the binary point to the left of all 32 bits, a fraction in the range 0..(1 - 2**(-32)). Treat 100 as a special case and set the fraction to the maximum possible value. I don't have my 68030 manual handy, but I believe it is something like this: unsigned long percentage, threshold; asm { moveq percentage, d0 cmp.l #100, d0 bcc @1 /* percentage is < 100 */ moveq #0, d1 divu.l #100, d0:d1 move.l d1, threshold /* quotient is fraction */ bra @2 /* percentage is >= 100: use maximum fraction */ @1: move.l #0xffffffff, threshold @2: } 2) Generate the random number in the conventional fashion, e.g.: extern unsigned long rand(); asm { rand: move.l newRand, d0 mulu.l #1103515245, d0 add.l #12345, d0 /* note: ADD.L rather than ADD.W */ move.l d0, newRand rts } 3) Perform the threshold operation with an unsigned comparison: if (rand() <= threshold) { /* set the pixel */ } If this still isn't fast enough, and you are willing to sacrifice randomness, you might consider using 16-bit arithmetic. The choice of the multiplier and addend are important, so if you go this route you'll need to do some further research (Knuth is a good place to start). - -- (Dr.) John Bruner, Deputy Director bruner@csrd.uiuc.edu Center for Supercomputing Research & Development (217) 244-4476 (voice) University of Illinois at Urbana-Champaign (217) 244-1351 (FAX) 465 CSRL, MC-255; 1308 West Main St.; Urbana, IL 61801-2307 +++++++++++++++++++++++++++ From: lipa@camis.Stanford.EDU (Bill Lipa) Date: 6 Aug 92 16:00:59 GMT Organization: Stanford School of Medicine Try the algorithm for equation 7 described in section 3.2.2 of Knuth. It doesn't require any multiplication, division, or shifts, so it is probably faster than the other methods that have been discussed. It uses a table of 55 random numbers that can be generated slowly (or even precomputed) to make a sequence of 2^55 - 1 new pseudo-random numbers. Knuth chapter 3 is really the place to go for random number techniques. Bill Lipa lipa@camis.stanford.edu +++++++++++++++++++++++++++ From: pgj@Apple.COM (Paul Jensen) Date: 6 Aug 92 21:51:30 GMT Organization: A/UX Engineering, Apple Computer Inc. All the comments in the previous replies are on target: "%" is slow, mod-power-of-two is fast, you're better off using a dithering algorithm to accomplish what you want. However... if you *really* need a fast random numnber generator, there are algorithms better than the ones presented here, most of which are variations on the Linear (Lehmer) Congruential method. In a previous incarnation writing Monte-Carlo simulators, I was fond of the Feedback Shift Register algorithm which is not only has better statistical properties, but is fast: 2 adds, 2 compares, and one XOR (i.e. *no* multiply). See JACM Vol. 20, #3, July '73, pp 456-68 for details (as well as some of the ugliest FORTRAN you will ever lay eyes on). The 2nd edition of Knuth Vol 2 is probably the last word on this subject: 170+ pages of mind-numbing detail. Knuth favors a different algorithm, but he is less concerned with speed. /PGJ --------------------------- From: gurgle@netcom.com (Pete Gontier) Subject: MacTCP: can't send very many single bytes in a row Date: 30 Jul 92 02:34:55 GMT Organization: cellular Last night I tried to do an intuitive thing: base a function called tcp_puts on a function called tcp_putchar. tcp_puts was, of course, calling tcp_putchar for each character in the string, and tcp_putchar was sending each character to a (Mac)TCP connection. I knew this was inefficient, but I wanted to see just *how* inefficient it was. Turns out it was more than inefficient; after a few characters, it *hung*. So now I don't have a tcp_putchar; I just blast the entire string every time with tcp_puts and if I need to output a single char, I fake a string and send it to tcp_puts. I don't send a single character any too often, so that is not a problem. So the question is --- is this hanging behavior a widely experienced thing? An acknowledged bug, perhaps? FYI, I'm using MacTCP 1.1. - -- Pete Gontier // EC Technology // gurgle@netcom.com +++++++++++++++++++++++++++ From: peter@cujo.curtin.edu.au (Peter N Lewis) Organization: NCRPDA, Curtin University Date: Mon, 3 Aug 1992 00:58:08 GMT In article <p-pmarm.gurgle@netcom.com>, gurgle@netcom.com (Pete Gontier) wrote: > So the question is --- is this hanging behavior a widely experienced > thing? An acknowledged bug, perhaps? > > FYI, I'm using MacTCP 1.1. MacTCP is an acknowledged bug :-) Were you using asyncronous sends? That would definitely cause a problem since there is invariably a limit to the number of async control calls you can have at any time (this bit me baddly in the .XPP driver where it happily said 'yeah, sure I can do that asyncronously' and threw it away)-: As a side note, it is generally better to write a routine for puts instead of putchar and have putchar call puts instead - if you are writing a string this will be much more efficient, and if you are writing a char it will only be mildly less efficent, and as a general rule, you write more strings than chars. This would apply to any kind of writes, TCP, ADSP, File System, serial lines whatever. Have fun, Peter. _______________________________________________________________________ Peter N Lewis, NCRPDA, Curtin University peter@cujo.curtin.edu.au GPO Box U1987, Perth WA 6001, AUSTRALIA FAX: +61 9 367 8141 +++++++++++++++++++++++++++ From: gurgle@netcom.com (Pete Gontier) Date: Mon, 03 Aug 92 04:44:48 GMT Organization: cellular peter@cujo.curtin.edu.au (Peter N Lewis) writes: >Were you using asyncronous sends? That would definitely cause a problem >since there is invariably a limit to the number of async control calls you >can have at any time (this bit me baddly in the .XPP driver where it >happily said 'yeah, sure I can do that asyncronously' and threw it away)-: Unfortunately, they were synchronous sends. About 20 1-byte synchronous sends. >As a side note, it is generally better to write a routine for puts instead >of putchar and have putchar call puts... After a while, I decided that was the case. But it's still more intuitive to do it the other way around, and I had to be forced into doing it this way before I realized it was better. - -- Pete Gontier // EC Technology // gurgle@netcom.com +++++++++++++++++++++++++++ From: ejohnson@void.ncsa.uiuc.edu (Eric E. Johnson) Organization: University of Illinois at Urbana Date: Wed, 5 Aug 1992 20:30:45 GMT peter@cujo.curtin.edu.au (Peter N Lewis) writes: >Were you using asyncronous sends? That would definitely cause a problem >since there is invariably a limit to the number of async control calls you >can have at any time (this bit me baddly in the .XPP driver where it >happily said 'yeah, sure I can do that asyncronously' and threw it away)-: Does anyone know what that limit is? Is the limit related to how many async calls are placed, or is it the number of async calls that have yet to complete? Eric +++++++++++++++++++++++++++ From: peter@cujo.curtin.edu.au (Peter N Lewis) Organization: NCRPDA, Curtin University Date: Sun, 9 Aug 1992 05:34:39 GMT In article <ejohnson.713046645@void>, ejohnson@void.ncsa.uiuc.edu (Eric E. Johnson) wrote: > > peter@cujo.curtin.edu.au (Peter N Lewis) writes: > > >Were you using asyncronous sends? That would definitely cause a problem > >since there is invariably a limit to the number of async control calls you > >can have at any time (this bit me baddly in the .XPP driver where it > >happily said 'yeah, sure I can do that asyncronously' and threw it away)-: > > Does anyone know what that limit is? Is the limit related to how many > async calls are placed, or is it the number of async calls that have > yet to complete? There is a table of machine dependent limits in IM V-519, including the number of concurrent ATP SendRequests (6-12), concurrent ATP Responses (8-32), Concurrent NBP Requests (1-10). I'm not sure about the limit of XPP async calls, its probabbly directly related to the limit of ASP calls. HTH, Peter. _______________________________________________________________________ Peter N Lewis, NCRPDA, Curtin University peter@cujo.curtin.edu.au GPO Box U1987, Perth WA 6001, AUSTRALIA FAX: +61 9 367 8141 --------------------------- From: gb2a+@andrew.cmu.edu (George J. Baxter) Subject: AppleEvent passing address Date: 4 Aug 92 11:20:13 GMT Organization: Science & Technology Center, Carnegie Mellon, Pittsburgh, PA Dear World: I'm trying to pass a pointer to a string through an appleEvent to another program. A tiny little problem occurs when I try to use this address, however, and that is that I get a nice bus error. So pleasing to the eye to see that MacsBug screen pop up. Anyway, why is this occurring, and how do I go about doing this correctly? Much Grace, -George Baxter - ----------------------- gb2a@andrew.cmu.edu baxter@a.cfr.cmu.edu "Only a Hawaiian can say Humuhumunukunukuapuaa five times fast, correctly." "I think we're in for a bad spell of wether." +++++++++++++++++++++++++++ From: jpugh@apple.com (Jon Pugh) Date: 8 Aug 92 03:46:03 GMT Organization: Apple Computer, Inc. In article <keThVha00UzxE3g1ht@andrew.cmu.edu>, gb2a+@andrew.cmu.edu (George J. Baxter) wrote: > > Dear World: > I'm trying to pass a pointer to a string through an appleEvent to > another program. A tiny little problem occurs when I try to use this > address, however, and that is that I get a nice bus error. So pleasing > to the eye to see that MacsBug screen pop up. Anyway, why is this > occurring, and how do I go about doing this correctly? Rule #1 DON'T DON'T DON'T DON'T DON'T DON'T DON'T DON'T DON'T DON'T DON'T DON'T DON'T Rule #2 Pretend like there is memory protection and every application has it's own inalienable partition. Rule #3 Don't even THINK about passing pointers around in AppleEvents. Rule #4 Pass the data, not the reference. Rule #5 There is NO rule 5. Rule #6 No poofters. Jon Disclaimer: We're very flexible on the no poofters rule. Rule #5 is absolute though. +++++++++++++++++++++++++++ From: daven@notable.com (Dave Newman) Date: Sat, 8 Aug 92 18:11:54 PST Organization: Notable Technologies, Inc. In article <jpugh-070892204135@90.20.3.205> (comp.sys.mac.programmer), jpugh@apple.com (Jon Pugh) writes: | In article <keThVha00UzxE3g1ht@andrew.cmu.edu>, gb2a+@andrew.cmu.edu | (George J. Baxter) wrote: | > | > Dear World: | > I'm trying to pass a pointer to a string through an appleEvent to | > another program. A tiny little problem occurs when I try to use this | > address, however, and that is that I get a nice bus error. So pleasing | > to the eye to see that MacsBug screen pop up. Anyway, why is this | > occurring, and how do I go about doing this correctly? | | Rule #1 | | DON'T DON'T DON'T DON'T DON'T DON'T DON'T DON'T DON'T DON'T DON'T DON'T | DON'T << remaining rules deleted for brevity >> There's a corollary worth noting. Corollary #1 Passing another application a pointer into your heap, whether it be AppleEvents, PPC, or your own private IAC hack, is just asking for that application to screw with your data, corrupt your heap, and generally wreak havoc. In short, pointer out, garbage in. - --Dave - ----------------------------------------------------------- Dave Newman | AOL: AFC Tinman Artillery Spotter | ALink: TINMAN Notable Technologies, Inc. | CIS: 70743,3323 Voice: 510.208.4449 | internet: daven@notable.com FAX: 510.444.4493 | - ----------------------------------------------------------- --------------------------- From: mgraf@sydvm1.VNET.IBM.COM (Michael Graf) Date: Mon, 10 Aug 92 10:05:57 EST Subject: THINK Pascal v4.01 and 32-bit Organization: Australian Programming Centre (IBMA) Basic Question: Is THINK Pascal v4.01 32-bit Compatible ? Reason: I recently went back to THINK Pascal to try a new program I had in mind, and had real problems getting my program to run, after it had compiled successfully. Every time I selected a menu THINK Pascal would give me an "Application Zone Damaged..." or "Bus Error" message, and all things would slowly die (generally my system goes down). I checked all the MENU resources, checked other files and generally got annoyed. Finally, I went to a program that used to run without a problem from within THINK, and it also fell over. I excluded all extensions, and only then remembered my recent switch to 32-bit (after I purchased more memory). I've tried playing with the SIZE resource for my resource file, but cannot get it to run under 32-bit memory ON. Is there something I can do, withink THINK Pascal or elsewhere, or is the compiler just 32-bit unfriendly (and I thought it was System 7 usable). Any suggestions, advice or words of wisdom would be more than welcome, and gratefully appreciated. Thanx ********************************************************************** Regards, Michael Graf INTERNET: (mgraf@sydvm1.vnet.ibm.com) BITNET: (mgraf@vnet) ********************************************************************** +++++++++++++++++++++++++++ From: siegel@world.std.com (Rich Siegel) Date: 10 Aug 92 02:47:28 GMT Organization: GCC Technologies In article <19920809.170841.691@almaden.ibm.com> mgraf@sydvm1.VNET.IBM.COM (Michael Graf) writes: >Basic Question: Is THINK Pascal v4.01 32-bit Compatible ? Basic answer: yes. There is, however, a bug with menu handling that will manifest itself when THINK Pascal is loaded above the 16MB boundary. The problem is fixed, and the fix will be released whenever Symantec releases the THINK Pascal 4.0.2 patch. (I don't work there, I just know. :-]) In the meantime, set THINK Pascal's partition size sufficiently large so that its application heap resides entirely below 16MB, or run some other applications to take up the space above 16MB. R. - -- - ----------------------------------------------------------------------- Rich Siegel Internet: siegel@world.std.com Software Engineer & Toolsmith GCC Technologies --------------------------- End of C.S.M.P. Digest **********************